package com.easy.frame.base.service.tree;

import cn.hutool.core.util.ObjectUtil;
import com.easy.frame.base.basic.constant.DbConstants;
import com.easy.frame.base.basic.pojo.BaseTree;
import com.easy.frame.base.basic.pojo.vo.BaseTreeVO;
import com.easy.frame.base.basic.pojo.vo.DefaultTreeVO;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.List;

/**
 * 树状结构工具类
 *
 * @author zzf
 * @date 2020/7/30 11:14
 */
public class TreeHandler<T extends BaseTreeVO> {

    /**
     * 返回的树状结构类
     */
    private final Class<T> tClass;

    public TreeHandler(Class<T> tClass) {
        this.tClass = tClass;
    }

    /**
     * 创建指定类的TreeHandler
     *
     * @param tClass 继承{@link BaseTreeVO}的类
     * @return tClass的树状结构实例
     */
    public static TreeHandler<? extends BaseTreeVO> of(Class<? extends BaseTreeVO> tClass) {
        return new TreeHandler<>(tClass);
    }

    /**
     * 默认的TreeHandler，即返回{@link DefaultTreeVO}
     *
     * @return {@link DefaultTreeVO}
     */
    public static TreeHandler<? extends BaseTreeVO> defaultInstance() {
        return new TreeHandler<>(DefaultTreeVO.class);
    }

    /**
     * 递归生成树状结构
     */
    public T getTree(Collection<? extends BaseTree> list) {
        T treeVO = getNewInstance();
        treeVO.setName("所有");
        treeVO.setEnabled(DbConstants.DEFAULT_YES);
        treeVO.setOrderNum(1);
        getTree(list, treeVO);
        return treeVO;
    }

    /**
     * 递归生成树状结构
     */
    private void getTree(Collection<? extends BaseTree> list, T parentNode) {
        List<T> childList = new ArrayList<>();
        list.forEach(s -> {
            if (isChild(s, parentNode)) {
                T treeVO = doToDTO(s);
                if (!s.getLeafNode()) {
                    getTree(list, treeVO);
                }
                childList.add(treeVO);
            }
        });
        //排序
        if (ObjectUtil.isNotEmpty(childList)) {
            childList.sort(Comparator.comparingInt(T::getOrderNum));
        }
        parentNode.setChildList(childList);
    }

    /**
     * 对象转换
     */
    private T doToDTO(BaseTree treeDO) {
        T treeVO = getNewInstance();
        BeanUtils.copyProperties(treeDO, treeVO);
        return treeVO;
    }

    private T getNewInstance() {
        T treeVO;
        try {
            treeVO = tClass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return treeVO;
    }

    /**
     * 判断是否为其子节点
     *
     * @param treeDO     树状实体对象
     * @param parentNode 父级节点对象
     */
    private boolean isChild(BaseTree treeDO, T parentNode) {
        if (StringUtils.isEmpty(parentNode.getPath())) {
            return StringUtils.isEmpty(treeDO.getParentPath());
        } else {
            return parentNode.getPath().equals(treeDO.getParentPath());
        }
    }
}
